﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using AdoNet = System.Data;
using System.Globalization;

namespace DataSet4Com
{
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    [ComDefaultInterface(typeof(IDataTable))]
    [Guid("94BBD320-5A16-4AFE-829B-DA7643E68758")]
    public class DataTable : IDataTable
    {
        private AdoNet.DataTable _adoNetTable;

        public DataTable() : this(null)
        {
        }

        public DataTable(AdoNet.DataTable adoNetTable)
        {
            if (adoNetTable == null)
                _adoNetTable = new AdoNet.DataTable();
            else
                _adoNetTable = adoNetTable;
        }

        [ComVisible(false)]
        public AdoNet.DataTable AdoNetDataTable
        {
            get { return _adoNetTable; }
        }
                
        public bool CaseSensitive 
        {
            get { return _adoNetTable.CaseSensitive; }
            set { _adoNetTable.CaseSensitive = value; }
        }
        
        public DataRelationCollection ChildRelations 
        {
            get { return new DataRelationCollection(_adoNetTable.ChildRelations); }
        }
        
        public DataColumnCollection Columns
        {
            get { return new DataColumnCollection(_adoNetTable.Columns); }
        }
        
        public ConstraintCollection Constraints 
        {
            get { return new ConstraintCollection(_adoNetTable.Constraints); }
        }
        
        public DataSet DataSet 
        {
            get { return new DataSet(_adoNetTable.DataSet); }
        }
        
        //public DataView DefaultView { get; }
        
        public string DisplayExpression 
        {
            get { return _adoNetTable.DisplayExpression; }
            set { _adoNetTable.DisplayExpression = value; } 
        }               
        
        public bool HasErrors 
        {
            get { return _adoNetTable.HasErrors; }
        }
        
        public bool IsInitialized 
        {
            get { return _adoNetTable.IsInitialized; }
        }
        
        public string Locale 
        {
            get { return _adoNetTable.Locale.Name; }
            set { _adoNetTable.Locale = CultureInfo.GetCultureInfo(value); } 
        }
        
        public int MinimumCapacity 
        {
            get { return _adoNetTable.MinimumCapacity; }
            set { _adoNetTable.MinimumCapacity = value; }
        }
        
        public string Namespace 
        {
            get { return _adoNetTable.Namespace; }
            set { _adoNetTable.Namespace = value; }
        }
        
        public DataRelationCollection ParentRelations 
        {
            get { return new DataRelationCollection(_adoNetTable.ParentRelations); }
        }
        
        public string Prefix 
        {
            get { return _adoNetTable.Prefix; }
            set { _adoNetTable.Prefix = value; }
        }

        public DataColumnList PrimaryKey
        {
            get
            {
                DataColumn[] columns = (from column in _adoNetTable.PrimaryKey
                                        select new DataColumn(column)).ToArray();

                return new DataColumnList(columns);
            }
            set
            {
                AdoNet.DataColumn[] adoNetColumns = (from column in value.InternalList
                                                     select column.AdoNetDataColumn).ToArray();

                _adoNetTable.PrimaryKey = adoNetColumns;
            }
        }
        
        public SerializationFormat RemotingFormat 
        {
            get { return (SerializationFormat)((int)_adoNetTable.RemotingFormat); }
            set { _adoNetTable.RemotingFormat = (AdoNet.SerializationFormat)((int)value); }
        }
        
        public DataRowCollection Rows 
        {
            get { return new DataRowCollection(_adoNetTable.Rows); }
        }
                
        public string TableName 
        {
            get { return _adoNetTable.TableName; }
            set { _adoNetTable.TableName = value; }
        }

        public void AcceptChanges()
        {
            _adoNetTable.AcceptChanges();
        }

        public virtual void BeginInit()
        {
            _adoNetTable.BeginInit();
        }

        public void Clear()
        {
            _adoNetTable.Clear();
        }

        public virtual DataTable Clone()
        {
            return new DataTable(_adoNetTable.Clone());
        }

        public object Compute(string expression, string filter)
        {
            return _adoNetTable.Compute(expression, filter);
        }

        public DataTable Copy()
        {
            return new DataTable(_adoNetTable.Copy());
        }

        public virtual void EndInit()
        {
            _adoNetTable.EndInit();
        }

        public DataTable GetChanges()
        {
            return new DataTable(_adoNetTable.GetChanges());
        }

        public DataTable GetChangesOfRowState(DataRowState rowStates)
        {
            return new DataTable(_adoNetTable.GetChanges((AdoNet.DataRowState)((int)rowStates)));
        }

        public DataRowList GetErrors()
        {
            DataRow[] rows = (from row in _adoNetTable.GetErrors()
                              select new DataRow(row)).ToArray();

            return new DataRowList(rows);
        }

        public void ImportRow(DataRow row)
        {
            _adoNetTable.ImportRow(row.AdoNetDataRow);
        }

        public void Merge(DataTable table, [Optional, DefaultParameterValue(false)] bool preserveChanges, [Optional, DefaultParameterValue(MissingSchemaAction.AddWithKey)] MissingSchemaAction missingSchemaAction)
        {
            _adoNetTable.Merge(table.AdoNetDataTable, preserveChanges, (AdoNet.MissingSchemaAction)((int)missingSchemaAction));
        }

        public DataRow NewRow()
        {
            return new DataRow(_adoNetTable.NewRow());
        }

        public void RejectChanges()
        {
            _adoNetTable.RejectChanges();
        }

        public virtual void Reset()
        {
            _adoNetTable.Reset();
        }

        public DataRowList Select([Optional, DefaultParameterValue("")] string filterExpression, [Optional, DefaultParameterValue("")] string sort)
        {
            DataRow[] result = (from row in _adoNetTable.Select(filterExpression, sort)
                                select new DataRow(row)).ToArray();

            return new DataRowList(result);
        }

        public new string ToString()
        {
            return _adoNetTable.ToString();
        }
    }

    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    [Guid("61B043BB-39C4-4B43-9341-9CB1362E3F23")]
    public interface IDataTable
    {
        bool CaseSensitive
        {
            get;
            set;
        }

        DataRelationCollection ChildRelations
        {
            get;
        }

        DataColumnCollection Columns
        {
            get;
        }

        ConstraintCollection Constraints
        {
            get;
        }

        DataSet DataSet
        {
            get;
        }

        //public DataView DefaultView { get; }

        string DisplayExpression
        {
            get;
            set;
        }

        bool HasErrors
        {
            get;
        }

        bool IsInitialized
        {
            get;
        }

        string Locale
        {
            get;
            set;
        }

        int MinimumCapacity
        {
            get;
            set;
        }

        string Namespace
        {
            get;
            set;
        }

        DataRelationCollection ParentRelations
        {
            get;
        }

        string Prefix
        {
            get;
            set;
        }

        DataColumnList PrimaryKey
        {
            get;
            set;
        }

        SerializationFormat RemotingFormat
        {
            get;
            set;
        }

        DataRowCollection Rows
        {
            get;
        }

        string TableName
        {
            get;
            set;
        }

        void AcceptChanges();

        void BeginInit();

        void Clear();

        DataTable Clone();

        object Compute(string expression, string filter);

        DataTable Copy();

        void EndInit();

        DataTable GetChanges();

        DataTable GetChangesOfRowState(DataRowState rowStates);

        DataRowList GetErrors();

        void ImportRow(DataRow row);

        void Merge(DataTable table, [Optional, DefaultParameterValue(false)] bool preserveChanges, [Optional, DefaultParameterValue(MissingSchemaAction.AddWithKey)] MissingSchemaAction missingSchemaAction);

        DataRow NewRow();

        void RejectChanges();

        void Reset();

        DataRowList Select([Optional, DefaultParameterValue("")] string filterExpression, [Optional, DefaultParameterValue("")] string sort);

        string ToString();
    }
}
